# python-resmon - Python tools for Resmon monitoring and the Circonus API
# Copyright (c) 2010 Crown coypright
# 
# This file is part of python-resmon.
# 
# python-resmon is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# python-resmon is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with python-resmon.  If not, see <http://www.gnu.org/licenses/>.

import sys
import os
import os.path
import time
import getpass
import subprocess
import urlparse
import urllib
import datetime

import gtk
try:
    import glib
except importError:
    import gobject as glib
from gtk import gdk
import pynotify

from circonus.api import CirconusAPI
from circonus.feed import CirconusAlertFeed
from ruleparse.loader import load
from checker.alert import Restored

DEFAULT_RULES_FILE = 'rules.cm'

# Don't show severities lower than this
MIN_SEVERITY = 3 

class Daemon(object):
    def start(self):
        if os.fork() != 0:
            sys.exit(0)
        self.run()

    def run(self):
        raise NotImplementedError("Subclasses must implement this method")


class MonitorDaemon(Daemon):
    def __init__(self, feed):
        self.feed = feed
        self.feed.add_alert_listener(self.handle_alert)

    def handle_alert(self, alert):
        if alert.severity > MIN_SEVERITY or isinstance(alert, Restored):
            return

        icon = os.path.abspath(os.path.join(os.path.dirname(__file__), 'icons/severity-%d.png' % alert.severity))
        n = pynotify.Notification(alert.host.hostname, alert.alert_string(), icon)
        n.attach_to_status_icon(self.icon)
        n.set_urgency(pynotify.URGENCY_CRITICAL)
        try:
            n.show()
        except glib.GError:
            # Silently ignore errors in displaying the alert
            pass

    def show_dashboard(self, sender):
        self.show_url('https://circonus.com/account/doc/dashboard')

    def show_fault_detection(self, sender):
        self.show_url('https://circonus.com/account/doc/fault-detection')

    def show_trending(self, sender):
        self.show_url('https://circonus.com/account/doc/trending')

    def show_popup_menu(self, icon, button, activate_time):
        m = gtk.Menu()

        def _add_item(name, handler):
            mi = gtk.MenuItem(name)
            mi.connect('activate', handler)
            m.append(mi)
            mi.show()

        _add_item('Dashboard', self.show_dashboard)
        _add_item('Graphs', self.show_trending)
        _add_item('Alerts', self.show_fault_detection)

        sep = gtk.SeparatorMenuItem()
        m.append(sep)
        sep.show()

        exit = gtk.MenuItem('E_xit')
        exit.connect('activate', self.exit)
        m.append(exit)
        exit.show()

        m.popup(None, None, gtk.status_icon_position_menu, button, activate_time, icon)

    def show_url(self, url):
        gtk.show_uri(gdk.screen_get_default(), url, gtk.get_current_event_time())

    def exit(self, sender):
        gtk.main_quit()

    def run(self):
        self.icon = gtk.status_icon_new_from_file('circonus.png')
        self.icon.connect('activate', self.show_dashboard)
        self.icon.connect('popup-menu', self.show_popup_menu)

        pynotify.init('Circonus Monitor')

        self.update()
        self.timer = glib.timeout_add_seconds(60, self.update)
        gtk.main()
    
    def update(self):
        self.feed.poll()
        return True # tell glib to continue polling


if __name__ == '__main__':
    from optparse import OptionParser

    parser = OptionParser()
    parser.add_option('-l', '--rules', help="Rules file to load", default=DEFAULT_RULES_FILE)
    parser.add_option('-d', '--daemon', action='store_true', help="Start as a daemon")

    options, args = parser.parse_args()

    circonus_account = CirconusAPI.from_config()
    rules = load(options.rules)

    feed = CirconusAlertFeed(circonus_account, rules)
    monitor = MonitorDaemon(feed)

    if options.daemon:
        monitor.start()
    else:
        monitor.run()

